Adding PalmDoc support
authorparkrrrr <parkrrrr@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Fri, 16 Apr 2004 16:48:05 +0000 (16:48 +0000)
committerparkrrrr <parkrrrr@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Fri, 16 Apr 2004 16:48:05 +0000 (16:48 +0000)
gpsbabel/Makefile
gpsbabel/README
gpsbabel/coldsync/pdb.c
gpsbabel/palmdoc.c [new file with mode: 0644]
gpsbabel/vecs.c

index 762a8c40be0b492ffa2bd4b586cc8b6fd8c892c8..49281616a3baab594eba22917f2d7cb83680bd0c 100644 (file)
@@ -19,7 +19,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o \
        psp.o holux.o garmin.o tmpro.o tpg.o \
        xcsv.o gcdb.o tiger.o internal_styles.o easygps.o quovadis.o \
        gpilots.o saroute.o navicache.o psitrex.o geoniche.o delgpl.o \
-       ozi.o nmea.o text.o html.o
+       ozi.o nmea.o text.o html.o palmdoc.o
 
 FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o reverse_route.o
 
@@ -107,7 +107,7 @@ mac-release:
        tar cvzf gpsbabel-osx.tgz usr/bin/gpsbabel
        curl -u anonymous:anonymous --upload-file gpsbabel-osx.tgz ftp://upload.sf.net/incoming/
 
-# Machine generated from here down.   
+# Machine generated from here down.  
 arcdist.o: arcdist.c defs.h queue.h grtcirc.h
 cetus.o: cetus.c defs.h queue.h coldsync/palm.h coldsync/pdb.h
 copilot.o: copilot.c defs.h queue.h coldsync/palm.h coldsync/pdb.h
@@ -131,6 +131,11 @@ gpsutil.o: gpsutil.c defs.h queue.h magellan.h
 gpx.o: gpx.c defs.h queue.h
 grtcirc.o: grtcirc.c defs.h queue.h
 holux.o: holux.c defs.h queue.h holux.h
+html.o: html.c defs.h queue.h jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h \
+  jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
+  jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
+  jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h \
+  jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
 internal_styles.o: internal_styles.c defs.h queue.h
 magnav.o: magnav.c defs.h queue.h coldsync/palm.h coldsync/pdb.h
 magproto.o: magproto.c defs.h queue.h magellan.h
@@ -139,7 +144,14 @@ mapsend.o: mapsend.c defs.h queue.h mapsend.h magellan.h
 mapsource.o: mapsource.c defs.h queue.h garmin_tables.h
 mkshort.o: mkshort.c defs.h queue.h
 navicache.o: navicache.c defs.h queue.h
+nmea.o: nmea.c defs.h queue.h
 ozi.o: ozi.c defs.h queue.h csv_util.h
+palmdoc.o: palmdoc.c defs.h queue.h jeeps/gpsmath.h jeeps/gps.h \
+  jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \
+  jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \
+  jeeps/gpsfmt.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \
+  jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h \
+  coldsync/palm.h coldsync/pdb.h
 pcx.o: pcx.c defs.h queue.h garmin_tables.h
 polygon.o: polygon.c defs.h queue.h
 position.o: position.c defs.h queue.h grtcirc.h
@@ -152,6 +164,11 @@ reverse_route.o: reverse_route.c defs.h queue.h
 route.o: route.c defs.h queue.h
 saroute.o: saroute.c defs.h queue.h
 smplrout.o: smplrout.c defs.h queue.h grtcirc.h
+text.o: text.c defs.h queue.h jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h \
+  jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
+  jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
+  jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h \
+  jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
 tiger.o: tiger.c defs.h queue.h csv_util.h
 tmpro.o: tmpro.c defs.h queue.h csv_util.h
 tpg.o: tpg.c defs.h queue.h jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h \
@@ -168,56 +185,62 @@ coldsync/pdb.o: coldsync/pdb.c coldsync/config.h coldsync/palm.h \
   coldsync/pdb.h
 coldsync/util.o: coldsync/util.c coldsync/config.h coldsync/pconn/util.h \
   coldsync/palm.h
-jeeps/gpsapp.o: jeeps/gpsapp.c jeeps/gps.h jeeps/gpsport.h \
-  jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
-  jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
-  jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \
-  jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
-jeeps/gpscom.o: jeeps/gpscom.c jeeps/gps.h jeeps/gpsport.h \
-  jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
-  jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
-  jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \
-  jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
-jeeps/gpsmath.o: jeeps/gpsmath.c jeeps/gps.h jeeps/gpsport.h \
-  jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
-  jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
-  jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \
-  jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h \
-  jeeps/gpsdatum.h
-jeeps/gpsmem.o: jeeps/gpsmem.c jeeps/gps.h jeeps/gpsport.h \
-  jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
-  jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
-  jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \
-  jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
-jeeps/gpsprot.o: jeeps/gpsprot.c jeeps/gps.h jeeps/gpsport.h \
-  jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
-  jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
-  jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \
-  jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
-jeeps/gpsread.o: jeeps/gpsread.c jeeps/gps.h jeeps/gpsport.h \
-  jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
-  jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
-  jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \
-  jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
-jeeps/gpsrqst.o: jeeps/gpsrqst.c jeeps/gps.h jeeps/gpsport.h \
-  jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
-  jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
-  jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \
-  jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
-jeeps/gpssend.o: jeeps/gpssend.c jeeps/gps.h jeeps/gpsport.h \
+jeeps/gpsapp.o: jeeps/gpsapp.c jeeps/gps.h defs.h queue.h jeeps/gpsport.h \
   jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
   jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
   jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \
   jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
-jeeps/gpsserial.o: jeeps/gpsserial.c jeeps/gps.h jeeps/gpsport.h \
+jeeps/gpscom.o: jeeps/gpscom.c jeeps/gps.h defs.h queue.h jeeps/gpsport.h \
   jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
   jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
   jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \
   jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
-jeeps/gpsutil.o: jeeps/gpsutil.c jeeps/gps.h jeeps/gpsport.h \
+jeeps/gpsmath.o: jeeps/gpsmath.c jeeps/gps.h defs.h queue.h \
+  jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \
+  jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \
+  jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \
+  jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \
+  jeeps/gpsnmeaget.h jeeps/gpsdatum.h
+jeeps/gpsmem.o: jeeps/gpsmem.c jeeps/gps.h defs.h queue.h jeeps/gpsport.h \
   jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \
   jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \
   jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \
   jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
-internal_styles.c: mkstyle.sh style/README.style style/arc.style style/csv.style style/custom.style style/dna.style style/fugawi.style style/gpsdrive.style style/gpsman.style style/mapconverter.style style/mxf.style style/nima.style style/s_and_t.style style/tabsep.style style/xmap.style style/xmapwpt.style
-       ./mkstyle.sh > $@ || (rm -f $@ ; exit 1)
+jeeps/gpsprot.o: jeeps/gpsprot.c jeeps/gps.h defs.h queue.h \
+  jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \
+  jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \
+  jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \
+  jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \
+  jeeps/gpsnmeaget.h
+jeeps/gpsread.o: jeeps/gpsread.c jeeps/gps.h defs.h queue.h \
+  jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \
+  jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \
+  jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \
+  jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \
+  jeeps/gpsnmeaget.h
+jeeps/gpsrqst.o: jeeps/gpsrqst.c jeeps/gps.h defs.h queue.h \
+  jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \
+  jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \
+  jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \
+  jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \
+  jeeps/gpsnmeaget.h
+jeeps/gpssend.o: jeeps/gpssend.c jeeps/gps.h defs.h queue.h \
+  jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \
+  jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \
+  jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \
+  jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \
+  jeeps/gpsnmeaget.h
+jeeps/gpsserial.o: jeeps/gpsserial.c jeeps/gps.h defs.h queue.h \
+  jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \
+  jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \
+  jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \
+  jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \
+  jeeps/gpsnmeaget.h
+jeeps/gpsutil.o: jeeps/gpsutil.c jeeps/gps.h defs.h queue.h \
+  jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \
+  jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \
+  jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \
+  jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \
+  jeeps/gpsnmeaget.h
+internal_styles.c: mkstyle.sh style/README.style style/arc.style style/csv.style style/custom.style style/dna.style style/fugawi.style style/gpsdrive.style style/gpsman.style style/mapconverter.style style/mxf.style style/nima.style style/s_and_t.style style/saplus.style style/tabsep.style style/xmap.style style/xmapwpt.style
+       ./mkstyle.sh > dep || (rm -f dep ; exit 1)
index 3915fd4d1ab04c9964681f9b74cd0fed740ea427..a3d06f3a06591029a1a1084974790a1b2720e098 100644 (file)
@@ -500,15 +500,48 @@ THE FORMATS
     TEXT
 
         This is a simple human readable version of the data file, handy for
-        listings of any type of waypoint files.
+        listings of any type of waypoint files.  Use the 'nosep' option
+        to suppress the lines of dashes between entries.  Use the 
+        'encrypt' option to encrypt hints from Groundspeak GPX files. 
+
+        The following command line reads a GPX file with Groundspeak extensions
+        and writes a text file with encrypted hints:
+
+        gpsbabel -i gpx -f 12345.gpx -o text,encrypt -F 12345.txt
 
     HTML
 
         HTML output generates a single HTML file of all of the waypoints in
         the input file.  It supports a number of Geocaching GPX extensions,
         as well as filters out potentially harmful HTML from the input file
-        while maintaining almost all of the source HTML formatting.
-
+        while maintaining almost all of the source HTML formatting.  Use the
+        'stylesheet' option to specify a CSS stylesheet to be used with the 
+        resulting HTML file.  Use the 'encrypt' option to encrypt hints from
+        Groundspeak GPX files.
+
+        The following command line reads a GPX file with Groundspeak extensions
+        and writes an HTML file with encrypted hints that is rendered using a
+        custom stylesheet:
+
+        gpsbabel -i gpx -f 12345.gpx \
+                 -o html,stylesheet=green.css,encrypt -F 12345.html
+
+    PALMDOC
+        PalmDoc output is similar to Text output, except that it generates 
+        a Palm Database (PDB) file suitable for use with programs like 
+        CSpotRun, TealDoc, AportisDoc, Palm Reader, and others.  The resulting
+        file also contains bookmarks to make it easy to jump to a particular
+        waypoint.  To suppress the dashed lines between waypoints, use the 
+        'nosep' option.  To specify a name for the document, use the 'dbname'
+        option.  Use the 'encrypt' option to encrypt hints from Groundspeak
+        GPX files.
+
+        The following command line reads a GPX file with Groundspeak extensions
+        and writes a Palm document with encrypted hints:
+
+        gpsbabel -i gpx -f 12345.gpx \
+                 -o "palmdoc,dbname=Unfound Geocaches,encrypt" -F 12345.pdb
 
 DATA FILTERS
 
index b7d4f9807f72d0da79f54c697a92fe50ae2cb5b3..a19e3fe0259b0c2b428a01d9dc2c0bb09913ef2f 100644 (file)
@@ -6,7 +6,7 @@
  *     You may distribute this file under the terms of the Artistic
  *     License, as specified in the README file.
  *
- * $Id: pdb.c,v 1.5 2004-01-19 18:15:22 robertl Exp $
+ * $Id: pdb.c,v 1.6 2004-04-16 16:47:51 parkrrrr Exp $
  */
 /* XXX - The way zero-length records are handled is a bit of a kludge. They
  * shouldn't normally exist, with the exception of expunged records. But,
@@ -865,8 +865,6 @@ pdb_AppendResource(struct pdb *db,
        return 0;                       /* Success */
 }
 
-#if 0
-
 /* pdb_InsertRecord
  * Insert 'newrec' into 'db', just after 'prev'. If 'prev' is NULL,
  * 'newrec' is inserted at the beginning of the list.
@@ -903,6 +901,7 @@ pdb_InsertRecord(struct pdb *db,    /* The database to insert into */
        return 0;                       /* Success */
 }
 
+#if 0
 /* pdb_InsertResource
  * Insert 'newrsrc' into 'db', just after 'prev'. If 'prev' is NULL, 'newrsrc'
  * is inserted at the beginning of the list.
diff --git a/gpsbabel/palmdoc.c b/gpsbabel/palmdoc.c
new file mode 100644 (file)
index 0000000..2e88406
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+    Output only format for PalmDoc
+
+    Copyright (C) 2004 Scott Brynen, scott (at) brynen.com
+    Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+    Copyright (C) 2004 Ronald L. Parker, ron@parkrrrr.com
+    Portions from txt2pdbdoc, Copyright (C) 1998  Paul J. Lucas
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+*/
+
+
+#include "defs.h"
+#include "jeeps/gpsmath.h"
+#include <ctype.h>
+#include "coldsync/palm.h"
+#include "coldsync/pdb.h"
+
+static FILE *file_out;
+static void *mkshort_handle;
+static void *mkshort_bookmark_handle;
+static const char *out_fname;
+static struct pdb *opdb;
+static struct pdb_record *opdb_rec;
+
+static char *suppresssep = NULL;
+static char *dbname = NULL;
+
+static int ct = 1;
+static int offset = 0;
+
+static char *encrypt;
+
+#define MYNAME "PALMDOC"
+
+/* constants */
+#define        BUFFER_SIZE     4096            /* big enough for uncompressed record */
+#define        COMPRESSED      2
+#define        COUNT_BITS      3               /* why this value?  I don't know */
+#define        DISP_BITS       11              /* ditto */
+
+#define        DOC_CREATOR     0x52454164      /* "REAd" */
+#define        DOC_TYPE        0x54455874      /* "TEXt" */
+#define        UNCOMPRESSED    1
+
+struct buffer {
+       unsigned char *data;
+       unsigned len;
+};
+
+#define        NEW_BUFFER(b)   (b)->data = (unsigned char *)xmalloc( ((b)->len = 0,BUFFER_SIZE) )
+
+static
+arglist_t palmdoc_args[] = {
+       { "nosep", &suppresssep, 
+               "Suppress separator lines between waypoints", ARGTYPE_BOOL },
+       {"dbname", &dbname, "Database name", ARGTYPE_STRING },
+       {"encrypt", &encrypt, "Encrypt hints with ROT13", ARGTYPE_BOOL },
+       {0, 0, 0, 0}
+};
+
+static struct buffer buf;
+
+struct doc_record0                   /* 16 bytes total */
+{
+    unsigned short version;          /* 1 = plain text, 2 = compressed */
+    unsigned short reserved1;
+    unsigned long  doc_size;         /* in bytes, when uncompressed */
+    unsigned short num_records;      /* PDB header numRecords - 1 */
+    unsigned short rec_size;         /* usually RECORD_SIZE_MAX */
+    unsigned long  reserved2;
+    unsigned short recsizes[1];
+};
+
+static struct recordsize {
+       int size;
+       struct recordsize *next;
+} *recordsize_tail;
+
+static struct bookmark {
+       int offset;
+       char *text;
+       struct bookmark *next;
+} *bookmark_tail;
+
+struct bookmark_record {
+       char text[16];
+       unsigned long offset;
+};
+
+static void put_byte(struct buffer *b, unsigned char c, int *space)
+{
+       if ( *space ) {
+               *space = 0;
+               /*
+               ** There is an outstanding space char: see if we can squeeze it
+               ** in with an ASCII char.
+               */
+               if ( c >= 0x40 && c <= 0x7F ) {
+                       b->data[ b->len++ ] = c ^ 0x80;
+                       return;
+               }
+               b->data[ b->len++ ] = ' ';      /* couldn't squeeze it in */
+       } else if ( c == ' ' ) {
+               *space = 1;
+               return;
+       }
+
+       if ( (c >= 1 && c <= 8) || c >= 0x80 )
+               b->data[ b->len++ ] = '\1';
+
+       b->data[ b->len++ ] = c;
+}
+
+static unsigned char * mem_find(unsigned char *t, int t_len, unsigned char *m, int m_len)
+{
+       register int i;
+       for ( i = t_len - m_len + 1; i > 0; --i, ++t )
+               if ( *t == *m && !memcmp( t, m, m_len ) )
+                       return t;
+       return 0;
+}
+
+
+static void compress( struct buffer *b )
+{
+
+       unsigned i, j;
+       int space = 0;
+
+       unsigned char *buf_orig;
+       unsigned char *p;       /* walking test hit; works up on successive matches */
+       unsigned char *p_prev;
+       unsigned char *head;    /* current test string */
+       unsigned char *tail;    /* 1 past the current test buffer */
+       unsigned char *end;     /* 1 past the end of the input buffer */
+
+       p = p_prev = head = buf_orig = b->data;
+       tail = head + 1;
+       end = b->data + b->len;
+
+       NEW_BUFFER( b );
+       b->len = 0;
+
+       /* loop, absorbing one more char from the input buffer on each pass */
+       while ( head != end ) {
+               /* establish where the scan can begin */
+               if ( head - p_prev > (( 1 << DISP_BITS )-1) )
+                       p_prev = head - (( 1 << DISP_BITS )-1);
+
+               /* scan in the previous data for a match */
+               p = mem_find( p_prev, tail - p_prev, head, tail - head );
+
+               /* on a mismatch or end of buffer, issued codes */
+               if ( !p || p == head || tail - head > ( 1 << COUNT_BITS ) + 2
+                       || tail == end
+               ) {
+                       /* issued the codes */
+                       /* first, check for short runs */
+            if ( tail - head < 4 ) {
+                               put_byte( b, *head++, &space );
+            }
+                       else {
+                               unsigned dist = head - p_prev;
+                               unsigned compound = (dist << COUNT_BITS)
+                                       + tail - head - 4;
+
+                /* for longer runs, issue a run-code */
+                               /* issue space char if required */
+                               if ( space ) {
+                                       b->data[ b->len++ ] = ' ';
+                                       space = 0;
+                               }
+
+                               b->data[ b->len++ ] = 0x80 + ( compound >> 8 );
+                               b->data[ b->len++ ] = compound & 0xFF;
+                               head = tail - 1;/* and start again */
+                       }
+                       p_prev = buf_orig;      /* start search again */
+               } else
+                       p_prev = p;             /* got a match */
+
+               /* when we get to the end of the buffer, don't inc past the */
+               /* end; this forces the residue chars out one at a time */
+               if ( tail != end )
+                       ++tail;
+       }
+       xfree( buf_orig );
+
+       if ( space )
+               b->data[ b->len++ ] = ' ';      /* add left-over space */
+
+       /* final scan to merge consecutive high chars together */
+       for ( i = j = 0; i < b->len; ++i, ++j ) {
+               b->data[ j ] = b->data[ i ];
+
+               /* skip run-length codes */
+               if ( b->data[ j ] >= 0x80 && b->data[ j ] < 0xC0 )
+                       b->data[ ++j ] = b->data[ ++i ];
+
+               /* if we hit a high char marker, look ahead for another */
+               else if ( b->data[ j ] == '\1' ) {
+                       b->data[ j + 1 ] = b->data[ i + 1 ];
+                       while ( i + 2 < b->len &&
+                               b->data[ i + 2 ] == 1 && b->data[ j ] < 8
+                       ) {
+                               b->data[ j ]++;
+                               b->data[ j + b->data[ j ] ] = b->data[ i + 3 ];
+                               i += 2;
+                       }
+                       j += b->data[ j ];
+                       ++i;
+               }
+       }
+       b->len = j;
+}
+
+static void write_header( void ) {
+       
+       int recs = ct-1;
+       --ct;
+       
+       struct doc_record0 *rec0 = xcalloc( 1, sizeof(struct doc_record0)+(ct-1)*sizeof(short));
+       be_write16( &rec0->version, COMPRESSED );
+       be_write16( &rec0->reserved1, 0 );
+       be_write32( &rec0->doc_size, offset );
+       be_write16( &rec0->num_records, ct );
+       be_write16( &rec0->rec_size, 4096 );
+       be_write32( &rec0->reserved2, 0 );
+       while ( recs ) {
+               struct recordsize *oldrec = recordsize_tail;
+               be_write16( &rec0->recsizes[recs], oldrec->size );
+               recordsize_tail = oldrec->next;
+               xfree( oldrec );
+               --recs;
+       }
+       
+       opdb_rec = new_Record (0, 0, 0, sizeof(struct doc_record0)+sizeof(short)*(ct-1), (const ubyte *)rec0);
+
+       if (opdb_rec == NULL) {
+               fatal(MYNAME ": libpdb couldn't create summary record\n");
+       }
+
+       if (pdb_InsertRecord(opdb, NULL, opdb_rec)) {
+               fatal(MYNAME ": libpdb couldn't insert summary record\n");
+       }
+}
+
+static void write_bookmarks( void ) {
+       struct bookmark *oldmark = NULL;
+       struct bookmark_record rec;
+
+       struct bookmark *newtail = NULL;
+
+       /* reverse the bookmark list */ 
+       while ( bookmark_tail ) {
+               oldmark = bookmark_tail;
+               bookmark_tail = oldmark->next;
+               oldmark->next = newtail;
+               newtail = oldmark;
+       }
+       bookmark_tail = newtail;
+       
+       ct++;
+       while ( bookmark_tail ) {
+               oldmark = bookmark_tail;
+               bookmark_tail = oldmark->next;
+               
+               be_write32( &rec.offset, oldmark->offset );
+               memset( rec.text, 16, 0 );
+               strncpy( rec.text, oldmark->text, 16 );
+               
+               opdb_rec = new_Record( 0, 0, ct++, 
+                               sizeof(struct bookmark_record),
+                                       (const ubyte *)&rec );
+               if (opdb_rec == NULL) {
+                       fatal(MYNAME ": libpdb couldn't create bookmark record\n");
+               }
+
+               if (pdb_AppendRecord(opdb, opdb_rec)) {
+                       fatal(MYNAME ": libpdb couldn't append bookmark record\n");
+               }
+
+               
+               xfree( oldmark );
+       } 
+}
+
+static void commit_buffer( void ) {
+
+       struct recordsize *newrec = xcalloc( 1, sizeof(struct recordsize));
+       newrec->next = recordsize_tail;
+       newrec->size = buf.len;
+       recordsize_tail = newrec;
+
+       compress( &buf );
+       
+        opdb_rec = new_Record (0, 0, ct++, buf.len, (const ubyte *)buf.data);
+
+        if (opdb_rec == NULL) {
+                fatal(MYNAME ": libpdb couldn't create record\n");
+        }
+
+        if (pdb_AppendRecord(opdb, opdb_rec)) {
+                fatal(MYNAME ": libpdb couldn't append record\n");
+        }
+
+}
+
+static void create_bookmark( char *bmtext ) {
+       struct bookmark *newmark = xcalloc( 1, sizeof(struct bookmark));
+       newmark->next = bookmark_tail;
+       newmark->offset = offset;
+       newmark->text = bmtext;
+       bookmark_tail = newmark;
+}      
+
+static void docprintf( int maxlen, char *format, ... ) {
+
+    char *txt = NULL;
+    char *txt2 = NULL;
+    va_list list;
+    int newlen;
+    int partlen;
+    
+    txt = xmalloc( maxlen );  
+       
+    va_start( list, format );
+    newlen = vsprintf( txt, format, list );
+
+    txt2 = txt;
+    offset += newlen;
+    while (txt2 && *txt2 ) {    
+        /* append to buffer what we can */
+       partlen = BUFFER_SIZE-1-buf.len;        
+       if ( buf.len + newlen + 1 > BUFFER_SIZE ) 
+       {
+           strncpy( buf.data+buf.len, txt2, partlen );
+            buf.data[BUFFER_SIZE-1] = '\0';
+            txt2 += partlen;
+            newlen -= partlen;
+            buf.len = BUFFER_SIZE-1;
+            commit_buffer();
+            NEW_BUFFER( &buf );
+        }
+        else { 
+            strcpy( buf.data+buf.len, txt2 );
+            buf.len += newlen;
+            txt2 = NULL;
+        }
+    }
+    
+    xfree( txt );   
+}
+
+static void docfinish() {
+       commit_buffer();
+       write_header();
+       write_bookmarks();
+}
+
+static void
+wr_init(const char *fname)
+{
+       file_out = xfopen(fname, "wb", MYNAME);
+        out_fname = fname;
+               
+       mkshort_handle = mkshort_new_handle();
+       mkshort_bookmark_handle = mkshort_new_handle();
+       ct = 1;
+       offset = 1;
+       recordsize_tail = NULL;
+       bookmark_tail = NULL;
+       NEW_BUFFER( &buf );
+}
+
+static void
+wr_deinit(void)
+{
+       fclose(file_out);
+       mkshort_del_handle(mkshort_handle);
+       mkshort_del_handle(mkshort_bookmark_handle);
+       
+        if ( dbname ) {
+            xfree(dbname);
+            dbname = NULL;
+       }
+}
+
+static void
+palmdoc_disp(const waypoint *wpt)
+{
+       int latint, lonint;
+       char tbuf[1024];
+       time_t tm = wpt->creation_time;
+       long utmz;
+       double utme, utmn;
+       char utmzc;
+
+        create_bookmark(mkshort(mkshort_bookmark_handle, wpt->description)); 
+       
+       lonint = abs(wpt->longitude);
+       latint = abs(wpt->latitude);
+
+       GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude, 
+               &utme, &utmn, &utmz, &utmzc);
+
+       if (tm == 0) 
+               tm = time(NULL);
+       strftime(tbuf, sizeof(tbuf), "%d-%b-%Y", localtime(&tm));
+
+       docprintf(300, "%-16s  %c%d %06.3f  %c%d %06.3f  (%ld%c %6.0f %7.0f)",
+               (global_opts.synthesize_shortnames) ? mkshort(mkshort_handle, wpt->description) : wpt->shortname,
+               wpt->latitude < 0 ? 'S' : 'N',  abs(latint), 60.0 * (fabs(wpt->latitude) - latint), 
+               wpt->longitude < 0 ? 'W' : 'E', abs(lonint), 60.0 * (fabs(wpt->longitude) - lonint),
+               utmz, utmzc, utme, utmn);
+       if (wpt->altitude != unknown_alt) 
+               docprintf (100, "  alt: %1.1f", wpt->altitude);
+       docprintf (10, "\n");
+       if (strcmp(wpt->description, wpt->shortname)) {
+               docprintf(10+strlen(wpt->description), "%s\n", wpt->description);
+       }
+       if (wpt->gc_data.terr) {
+               if (wpt->gc_data.desc_short.utfstring) {
+                       char *stripped_html = strip_html(&wpt->gc_data.desc_short);
+                       docprintf (10+strlen(stripped_html), "\n%s\n", stripped_html);
+                       xfree(stripped_html);
+                       }
+               if (wpt->gc_data.desc_long.utfstring) {
+                       char *stripped_html = strip_html(&wpt->gc_data.desc_long);
+                       docprintf (10+strlen(stripped_html), "\n%s\n", stripped_html);
+                       xfree(stripped_html);
+                       }
+               if (wpt->gc_data.hint) {
+                       char *hint = NULL;
+                       if ( encrypt )
+                               hint = rot13( wpt->gc_data.hint );
+                       else
+                               hint = xstrdup( wpt->gc_data.hint );
+                       docprintf (10+strlen(hint), "\nHint: %s\n", hint);
+                       xfree( hint );
+               }
+       }
+       else if (strcmp(wpt->notes,wpt->description)) {
+               docprintf (10+strlen(wpt->notes), "%s\n", wpt->notes);
+       }
+       if (! suppresssep) 
+               docprintf(50, "---------------------------\n");
+       else
+               docprintf(10, "\n");
+               
+       
+}
+
+static void
+data_write(void)
+{
+       
+        if (NULL == (opdb = new_pdb())) {
+                fatal (MYNAME ": new_pdb failed\n");
+        }
+
+        if ( dbname ) {
+            strncpy( opdb->name, dbname, PDB_DBNAMELEN );
+        }
+        else {
+            strncpy(opdb->name, out_fname, PDB_DBNAMELEN);
+        }
+        opdb->name[PDB_DBNAMELEN-1] = 0;
+        opdb->attributes = PDB_ATTR_BACKUP;
+        opdb->ctime = opdb->mtime = current_time() + 2082844800U;
+        opdb->type = DOC_TYPE; 
+        opdb->creator = DOC_CREATOR;
+        opdb->version = 1;
+       
+       if (! suppresssep) 
+               docprintf(50, "---------------------------\n");
+       setshort_length(mkshort_handle, 20 );
+       setshort_length(mkshort_bookmark_handle, 16);
+       setshort_whitespace_ok( mkshort_bookmark_handle, 0 );
+       waypt_disp_all(palmdoc_disp);
+
+        docfinish();   
+       pdb_Write(opdb, fileno(file_out));
+}
+
+
+ff_vecs_t palmdoc_vecs = {
+       ff_type_file,
+       NULL,
+       wr_init,
+       NULL,
+       wr_deinit,
+       NULL,
+       data_write,
+       palmdoc_args
+};
+
+
index c205bf5ebc9d227721d667bc6ddf5f066fc42ed2..8f2b5c4f6de6396ce5272e1e8a410b926ee1bbac 100644 (file)
@@ -61,6 +61,7 @@ extern ff_vecs_t gpl_vecs;
 extern ff_vecs_t ozi_vecs;
 extern ff_vecs_t nmea_vecs;
 extern ff_vecs_t text_vecs;
+extern ff_vecs_t palmdoc_vecs;
 extern ff_vecs_t html_vecs;
 
 static
@@ -258,6 +259,12 @@ vecs_t vec_list[] = {
                "HTML Output",
                NULL
        },
+       {
+               &palmdoc_vecs,
+               "palmdoc",
+               "PalmDoc Output",
+               NULL
+       },
        {
                NULL,
                NULL,